import 'package:base_lib/router/parameters.dart';
import 'package:flutter/cupertino.dart';
import 'ibus.dart';

class EventBus implements IEventBus {
  static EventBus get instance => _getInstance();
  static EventBus _instance;

  EventBus._internal();

  static EventBus _getInstance() {
    if (_instance == null) {
      _instance = new EventBus._internal();
    }
    return _instance;
  }

  Map<String, Map<String, List<ISubscriber>>> _postMap = new Map();

  Map<String, Map<String, ISubscriber>> _getMap = new Map();

  /// 如果 [componentName] 为 null 会把事件注册到 'def'分组，
  /// 否则 注册到该[componentName]下
  /// [type] 为 [EventType.get]事件必须指定 [componentName]，get事件是给App组件化使用的
  ///
  /// 禁止手动注册 [EventType.get] 事件
  /// 禁止手动注册 [EventType.get] 事件
  /// 禁止手动注册 [EventType.get] 事件
  ///
  ///
  @override
  void register(String event, ISubscriber subscriber,
      {String componentName, EventType type = EventType.post}) {
    if (type == EventType.get) {
      ///get事件必须指定 componentName
      assert(componentName != null);
      if (!_getMap.containsKey(componentName)) {
        _getMap[componentName] = {};
      }
      var eventMap = _getMap[componentName] ?? Map();
      if (eventMap.containsKey(event)) {
        throw Exception("在componentName：$componentName 已经有event：$event，无法重复注册");
      }
      eventMap[event] = subscriber;
      _getMap[componentName] = eventMap;
    } else {
      String eventGroup = componentName ?? 'def';
      var eventMap = _postMap[eventGroup] ?? Map();
      if (!eventMap.containsKey(event)) {
        eventMap[event] = new List();
      }
      eventMap[event].add(subscriber);
      _postMap[eventGroup] = eventMap;
    }
  }

  /// 如果 [componentName] 为 null, 会注销所有 'def' 分组下符合条件的事件
  /// 否则 注销该 [componentName] 的事件
  @override
  void unregister(String event, ISubscriber subscriber,
      {String componentName}) {
    String eventGroup = componentName ?? 'def';
    var eventMap = _postMap[eventGroup];
    if (eventMap.containsKey(event)) {
      eventMap[event].remove(subscriber);
    }
  }

  /// [componentName] == null 时 会向 'def' 分组下满足条件的事件发送
  /// 否则会调用[componentName]下的观察者
  @override
  void post(BuildContext context, String event, Parameters parameters,
      {String componentName}) {
    String eventGroup = componentName ?? 'def';
    var events = _postMap[eventGroup];
    if (events?.containsKey(event) ?? false) {
      events[event]?.forEach((subscriber) => subscriber(context, parameters));
    }
  }

  ///调用某个事件
  ///必须指定 componentName
  @override
  Future<Parameters> get(BuildContext context, String event,
      Parameters parameters, String componentName) async {
    if (_getMap.containsKey(componentName)) {
      var events = _getMap[event];
      if (events.containsKey(event)) {
        var subscriber = events[event];
        return await subscriber(context, parameters);
      }
    }
    throw Exception("无法在package：$componentName 下找到事件：$event");
  }
}
